home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
COMM
/
TR3_20.ARJ
/
TRFIFO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-02
|
9KB
|
312 lines
/*
* Filename: TRFIFO.C
* Author: Douglas Thomson, MUCG, Churchill, Victoria, AUSTRALIA
* Status: Public Domain
* History: 02-Dec-91 prepared source code for release
*/
/*
* trfifo: link two users via UNIX FIFO files
*
* Instructions:
* 1. run trfifo on the HOST PC:
* trfifo host
* 2. enter any name, say "test" at the prompt
* 3. exit to DOS, but KEEP connection
* 4. run TRHOST
* 5. run trfifo on the REPLICA PC:
* trfifo
* 6. enter the SAME name ("test") at the prompt
* 7. exit to DOS, but KEEP connection (if not using TR to log in)
* 8. run TR (if not using TR to log in)
* 9. when finished, exit TR with F10/3 (host PC will reboot)
* 10. normally host will keep running trfifo ready for next login. To
* stop trfifo on host, send DEL from host PC.
*/
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <termio.h>
#include <sys/ioctl.h>
#define TRUE 1
#define FALSE 0
#define OK 0
#define ERROR (-1)
#define FIFO ( S_IFIFO | 0666 )
#define IN 0
#define OUT 1
#define BUFF_SIZE 128
struct termio oldtty, tty; /* used for setting RAW I/O */
int iofd = 0; /* file descriptor for setting RAW I/O */
char readfile[BUFF_SIZE]; /* name of host input FIFO */
char writefile[BUFF_SIZE]; /* name of host output FIFO */
/*
* restore tty to its original state
*/
void terminate(status)
int status;
{
/*
* go back to normal I/O - borrowed from rbsb.c from the zmodem
* package.
*/
(void) ioctl(iofd, TCSBRK, 1); /* wait for output to drain */
(void) ioctl(iofd, TCFLSH, 1); /* flush input queue */
(void) ioctl(iofd, TCSETAW, &oldtty); /* restore original modes */
(void) ioctl(iofd, TCXONC,1); /* restart output */
/*
* don't leave inactive pipes around
*/
unlink(readfile);
unlink(writefile);
exit(status);
}
/*
* trap interrupts so that tty state can be restored
*/
void int_handler()
{
terminate(0);
}
void main(argc, argv)
int argc;
char *argv[];
{
char sys_name[256]; /* base name of FIFO link */
unsigned char buff[BUFF_SIZE]; /* buffer for transferred characters */
int n; /* number of characters read */
unsigned char c; /* a general purpose character! */
int readfd; /* file descriptor for reading FIFO */
int writefd; /* file descriptor for writing FIFO */
int child; /* PID for child process */
int host; /* is this the host end? */
static struct sigaction act; /* used for catching BREAK */
int first = TRUE; /* first time around? */
/*
* store settings for later
*/
(void) ioctl(iofd, TCGETA, &oldtty);
restart: /* come back here after each session */
/*
* ignore BREAK for a bit
*/
tty = oldtty; /* save original settings for later */
tty.c_iflag &= ~BRKINT; /* DO NOT allow BREAK to kill */
tty.c_iflag |= IGNBRK; /* ignore BREAK */
(void) ioctl(iofd, TCSETAW, &tty);
if (first) {
if (argc > 3 || (argc == 3 && strcmp(argv[1], "host") != 0)) {
fprintf(stderr, "Usage: trfifo [host] [<FIFO name>]\n");
terminate(1);
}
if (argc > 1 && strcmp(argv[1], "host") == 0) {
host = TRUE;
}
else {
host = FALSE;
}
if (argc != 3) { /* no output for command line version of host */
printf("TRFifo PC linking utility\n");
}
if (argc == host + 1) {
printf("Enter system name (e.g. as1): ");
fflush(stdout);
gets(sys_name);
}
else {
strcpy(sys_name, argv[host+1]);
}
if (argc != 3) { /* no output for command line version of host */
printf("Setting up %s '%s'\n", host ? "host" : "replica", sys_name);
}
/*
* Name the FIFOs - the host gets sensible names, the replica gets
* reversed names!
*/
if (host) {
sprintf(readfile, "/tmp/in_%s", sys_name);
sprintf(writefile, "/tmp/out_%s", sys_name);
}
else {
sprintf(readfile, "/tmp/out_%s", sys_name);
sprintf(writefile, "/tmp/in_%s", sys_name);
}
}
/*
* Create the FIFOs
*/
if (host) {
umask(0); /* let anyone into the FIFO */
unlink(readfile); /* kill old FIFO from last crash? */
if (mknod(readfile, FIFO) == ERROR) {
perror(readfile);
terminate(1);
}
unlink(writefile);
if (mknod(writefile, FIFO) == ERROR) {
perror(writefile);
unlink(readfile);
terminate(1);
}
}
if (host && first) {
printf("Return to DOS (keeping connection) and run TRHOST\n");
fflush(stdout);
}
/*
* catch interrupt
*/
act.sa_handler = int_handler;
sigaction(SIGINT, &act, NULL);
/*
* pipes are opened in the opposite order, so that deadlock does
* not occur waiting to open pipes...
*/
if (host) {
if ((readfd = open(readfile, O_RDONLY)) == ERROR) {
perror("can't open FIFO for reading");
unlink(readfile);
unlink(writefile);
terminate(1);
}
if ((writefd = open(writefile, O_WRONLY)) == ERROR) {
perror("can't open FIFO for writing");
unlink(readfile);
unlink(writefile);
terminate(1);
}
}
else {
if ((writefd = open(writefile, O_WRONLY)) == ERROR) {
/*
* This probably means the host is not running or is in use
* by someone else...
*/
fprintf(stderr, "Sorry, '%s' is not currently available\n",
sys_name);
terminate(1);
}
if ((readfd = open(readfile, O_RDONLY)) == ERROR) {
perror("can't open FIFO for reading");
terminate(1);
}
}
/*
* have established the FIFO, remove the files so no-one else can
* interfere...
*/
unlink(readfile);
unlink(writefile);
if (!host) {
printf("Return to DOS (keeping connection) and run TR\n");
fflush(stdout);
}
first = FALSE;
/*
* go into transparent 8-bit raw I/O etc etc - largely inspired by the
* rbsb.c file in the zmodem package. See this file for ideas if you
* have an incompatible flavor of UNIX...
*/
tty = oldtty; /* save original settings for later */
tty.c_iflag = BRKINT; /* DO allow BREAK to kill */
tty.c_lflag &= ~(ECHO | ICANON | ISIG); /* no echo etc etc*/
tty.c_oflag = 0; /* no output processing */
tty.c_cflag &= ~PARENB; /* disable parity */
tty.c_cflag |= CS8; /* set character size to 8 bits */
tty.c_cc[VMIN] = BUFF_SIZE; /* try to read a decent block */
tty.c_cc[VTIME] = 1; /* give up after 0.1 seconds */
(void) ioctl(iofd, TCSETAW, &tty);
/*
* One process reads the input FIFO and copies it to STDOUT; the other
* reads STDIN and copies it to the output FIFO.
*/
switch (child = fork()) {
case ERROR:
perror("fork");
terminate(1);
case 0:
for (;;) {
n = read(0, buff, BUFF_SIZE);
if (n > 0) {
write(writefd, buff, n);
}
}
default:
for (;;) {
if ((n = read(readfd, buff, BUFF_SIZE)) <= 0) {
break;
}
write(1, buff, n);
}
if (host) {
/*
* the replica has just terminated, so send a reboot command
* to the host
*/
/*
* ensure BREAK is ignored before rebooting PC
*/
tty = oldtty; /* save original settings for later */
tty.c_iflag &= ~BRKINT; /* DO NOT allow BREAK to kill */
tty.c_iflag |= IGNBRK; /* ignore BREAK */
(void) ioctl(iofd, TCSETAW, &tty);
c = 0;
write(1, &c, 1);
write(1, &c, 1);
c = 3;
write(1, &c, 1);
sleep(1);
c = 0;
write(1, &c, 1);
write(1, &c, 1);
c = 3;
write(1, &c, 1);
kill(child, SIGINT); /* don't leave orphan */
wait(NULL);
goto restart;
}
/*
* don't leave orphan processes...
*/
kill(child, SIGINT);
wait(NULL);
}
terminate(0);
}